package com.myimooc.shiro.web.realm;

import com.myimooc.shiro.web.dao.UserMapper;
import com.myimooc.shiro.web.vo.User;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Set;
import java.util.HashSet;

/**
 * @className: CustomRealm
 * @description: 自定义Realm
 * @date: 2020/5/12
 * @author: cakin
 */
// 仿照jdbcRealm继承 AuthorizingRealm
public class CustomRealm extends AuthorizingRealm {
    /**
     * userMapper
     */
    @Autowired
    private UserMapper userMapper;

    /**
     * 功能描述：授权
     *
     * @param principals 主要是从中取得用户姓名
     * @return AuthorizationInfo 认证信息，里面封装了角色和权限信息
     * @author cakin
     * @date 2020/5/12
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals ) {
        String userName = (String) principals.getPrimaryPrincipal();
        // 通过用户名获取角色数据
        Set<String> roles = getRolesByUserName(userName);
        // 通过用户名获取权限数据
        Set<String> permissions = getPermissionsByUserName(userName);
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.setRoles(roles);
        authorizationInfo.setStringPermissions(permissions);
        return authorizationInfo;
    }

    /**
     * 模拟从数据库或缓存中获取权限数据，某用户关联的权限
     *
     * @param userName 用户名
     * @return 权限数据
     */
    private Set<String> getPermissionsByUserName( String userName ) {
        Set<String> permissions = new HashSet<>();
        permissions.add("user:delete");
        permissions.add("user:add");
        return permissions;
    }

    /**
     * 从数据库中获取角色数据，某用户关联的角色
     *
     * @param userName 用户名
     * @return Set<String> 角色数据集合
     */
    private Set<String> getRolesByUserName( String userName ) {
        System.out.println("从数据库中获取授权数据");
        List<String> roles = userMapper.queryRolesByUserName(userName);
        return new HashSet<>(roles);
    }

    /**
     * 认证
     *
     * @param token 主体传送过来的认证信息
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token ) throws AuthenticationException {
        // 获取用户名
        String userName = (String) token.getPrincipal();
        // 通过用户名到数据库中获取凭证
        String password = getPasswordByUserName(userName);
        if (password == null) {
            return null;
        }
        // 从数据库查询得到的认证信息，封装到authenticationInfo中
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(userName, password, "customRealm");
        return authenticationInfo;
    }

    /**
     * 数据库查询凭证
     *
     * @param userName 用户名
     * @return String 凭证，这里是密码
     */
    private String getPasswordByUserName( String userName ) {
        User user = userMapper.getUserByUserName(userName);
        if (user != null) {
            return user.getPassword();
        }
        return null;
    }

    /**
     * 功能描述：用于测试
     *
     * @author cakin
     * @date 2020/5/13
     * @param args 参数
     */
    public static void main( String[] args ) {
        Md5Hash md5Hash = new Md5Hash("123456", "Mark");
        System.out.println(md5Hash.toString());
    }

}
